
#include <vector>
#include <algorithm>

#include <stdlib.h>

#include "AlsaOpt.h"

#include "alsa/asoundlib.h"

// 外部参数传入wav文件 路径
/*
    Usage: 
    Record : ./AlsaTool
    Play   : ./AlsaTool <wav file>
    Check Header : ./AlsaTool check <wav file>
*/




int TestAlsaMain(int argc, char *argv[])
{
    if (argc == 1)
    {
        RecordAudio("Record.wav", 8);

        return 0;
    }
    else if (argc == 2) 
    {
        char cstrArg[256] = {0};
        strncpy(cstrArg, argv[1], sizeof(cstrArg)-1);

        if (IsAudioFile(cstrArg))
        {
            PlayWavFile(cstrArg);
        }
    }
    else if (argc == 3)
    {
        std::string strCmd(argv[1]);
        if ( strCmd != "check" )
        {
            printf("wrong command for check header\n");
            return 0;
        }

        PrintWavFileInfo(argv[2]);
    }
    else if (argc == 4)
    {
        int iStartPos = std::stoi(argv[2]);
        int iDuration = std::stoi(argv[3]);
        play_selected_audio(argv[1], iStartPos, iDuration);

    }
    else
    {
        ShowHelpInfo();
    }

    return 0;
}


// 设置 PCM 硬件参数
static int set_hw_params(snd_pcm_t *pcmHandler, unsigned int sample_rate, unsigned short channels, unsigned short bits_per_sample) 
{
    snd_pcm_hw_params_t *hwParams;
    int ret;
    snd_pcm_uframes_t buffer_size, period_size;
    int dir;

    // 分配硬件参数对象
    snd_pcm_hw_params_malloc(&hwParams);

    do {
        // 初始化硬件参数
        ret = snd_pcm_hw_params_any(pcmHandler, hwParams);
        if (ret < 0) {
            fprintf(stderr, "snd_pcm_hw_params_any error: %s\n", snd_strerror(ret));
            break;
        }

        // 设置访问类型: 交错模式
        ret = snd_pcm_hw_params_set_access(pcmHandler, hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
        if (ret < 0) {
            fprintf(stderr, "snd_pcm_hw_params_set_access error: %s\n", snd_strerror(ret));
            break;
        }

        // 设置数据格式
        ret = snd_pcm_hw_params_set_format(pcmHandler, hwParams, bits_per_sample == 16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_U8);
        if (ret < 0) {
            fprintf(stderr, "snd_pcm_hw_params_set_format error: %s\n", snd_strerror(ret));
            break;
        }

        // 设置声道数
        ret = snd_pcm_hw_params_set_channels(pcmHandler, hwParams, channels);
        if (ret < 0) {
            fprintf(stderr, "snd_pcm_hw_params_set_channels error: %s\n", snd_strerror(ret));
            break;
        }

        // 设置采样率
        ret = snd_pcm_hw_params_set_rate_near(pcmHandler, hwParams, &sample_rate, &dir);
        if (ret < 0) {
            fprintf(stderr, "snd_pcm_hw_params_set_rate error: %s\n", snd_strerror(ret));
            break;
        }

        // 设置周期大小
        snd_pcm_hw_params_get_period_size(hwParams, &buffer_size, &dir);
        period_size = buffer_size / 4;
        ret = snd_pcm_hw_params_set_period_size_near(pcmHandler, hwParams, &period_size, &dir);
        if (ret < 0) {
            fprintf(stderr, "snd_pcm_hw_params_set_period_size error: %s\n", snd_strerror(ret));
            break;
        }

        // 应用硬件参数
        ret = snd_pcm_hw_params(pcmHandler, hwParams);
        if (ret < 0) {
            fprintf(stderr, "snd_pcm_hw_params error: %s\n", snd_strerror(ret));
            break;
        }

        // 释放硬件参数对象
        snd_pcm_hw_params_free(hwParams);
        return 0;
    } while (0);

    // 错误处理，释放硬件参数对象
    snd_pcm_hw_params_free(hwParams);
    return -1;
}



void PrintWavFileInfo(const char * cstrFileName)
{
    /**/
    RIFF_t wav_riff;
    FMT_t wav_fmt;
    DATA_t wav_data;

    int ret;
    off_t offset;

    int fd = open(cstrFileName, O_RDONLY);
    if (fd < 0) 
    {
        fprintf(stderr, "open error: %s: %s\n", cstrFileName, strerror(errno));
        return;
    }

    /* 读取 RIFF chunk */
    ret = read(fd, &wav_riff, sizeof(RIFF_t));
    if (sizeof(RIFF_t) != ret) 
    {
        if (ret < 0)
        {
            perror("read error");
        }            
        else
        {
            fprintf(stderr, "check error: %s\n", cstrFileName);
        }
        
        close(fd);
        return;
    }

    if (strncmp("RIFF", wav_riff.ChunkID, 4) || strncmp("WAVE", wav_riff.Format, 4)) 
    {
        fprintf(stderr, "check error: %s\n", cstrFileName);
        close(fd);
        return;
    }

    // offset = lseek(fd, 0, SEEK_CUR);  // offset = 12

    /* 读取 sub-chunk-fmt */
    ret = read(fd, &wav_fmt, sizeof(FMT_t));
    if (sizeof(FMT_t) != ret) 
    {
        if (ret < 0)
            perror("read error");
        else
            fprintf(stderr, "check error: %s\n", cstrFileName);
        close(fd);
        return;
    }

    if (strncmp("fmt ", wav_fmt.Subchunk1ID, 4)) 
    {
        fprintf(stderr, "check error: %s\n", cstrFileName);
        close(fd);
        return;
    }

    // offset = lseek(fd, 0, SEEK_CUR); // offset = 36

    // 跳过 fmt 子块可能的额外数据
    // wav_fmt.Subchunk1Size - (sizeof(FMT_t) - 8) = 0，所以这段代码没移动过指针偏移
    if (lseek(fd, wav_fmt.Subchunk1Size - (sizeof(FMT_t) - 8), SEEK_CUR) == -1) 
    {
        perror("lseek error");
        close(fd);
        return;
    }

    // printf("wav_fmt.Subchunk1Size - (sizeof(FMT_t) - 8) = %d(%u)\n", wav_fmt.Subchunk1Size - (sizeof(FMT_t) - 8), wav_fmt.Subchunk1Size - (sizeof(FMT_t) - 8));

    // offset = lseek(fd, 0, SEEK_CUR); // offset = 36

    // 查找 data 子块
    while (1) 
    {
        char subchunk_id[4];
        uint32_t subchunk_size;

        ret = read(fd, subchunk_id, 4);
        if (ret != 4) 
        {
            if (ret < 0) 
            {
                perror("read error");
            } 
            else 
            {
                fprintf(stderr, "check error: %s\n", cstrFileName);
            }
            close(fd);
            return;
        }

        ret = read(fd, &subchunk_size, 4);
        if (ret != 4) 
        {
            if (ret < 0) 
            {
                perror("read error");
            } 
            else 
            {
                fprintf(stderr, "check error: %s\n", cstrFileName);
            }
            close(fd);
            return;
        }

        printf("===============subchunk_id = %s, subchunk_size = %d(0x%x)\n", subchunk_id, subchunk_size, subchunk_size);

        // 直到找到"data"
        if (strncmp(subchunk_id, "data", 4) == 0) 
        {
            memcpy(wav_data.Subchunk2ID, subchunk_id, 4);
            wav_data.Subchunk2Size = subchunk_size;
            break;
        }

        // 跳过当前子块的数据部分
        if (lseek(fd, subchunk_size, SEEK_CUR) == -1) 
        {
            perror("lseek error");
            close(fd);
            return;
        }

        offset = lseek(fd, 0, SEEK_CUR);
        printf("跳过 %.*s 子块后文件偏移位置: %ld(0x%x) 字节\n", 4, subchunk_id, (long)offset, (unsigned int)offset);
    }

    offset = lseek(fd, 0, SEEK_CUR);    // offset = 140(0x8c)

    /* 打印音频文件的信息 */
    printf("<<<<音频文件格式信息>>>>\n\n");
    printf(" file name: %s\n", cstrFileName);
    printf(" wav_riff.ChunkSize = %u(0x%x)\n", wav_riff.ChunkSize, wav_riff.ChunkSize);
    printf(" Subchunk1Size: %u\n", wav_fmt.Subchunk1Size);
    printf(" AudioFormat: %u\n", wav_fmt.AudioFormat);
    printf(" NumChannels: %u\n", wav_fmt.NumChannels);
    printf(" SampleRate: %u(0x%x)\n", wav_fmt.SampleRate, wav_fmt.SampleRate);
    printf(" ByteRate: %u(0x%x)\n", wav_fmt.ByteRate, wav_fmt.ByteRate);
    printf(" BlockAlign: %u\n", wav_fmt.BlockAlign);
    printf(" BitsPerSample: %u\n\n", wav_fmt.BitsPerSample);

    printf("wav_data.Subchunk2ID = %.*s\n", 4, wav_data.Subchunk2ID);
    printf("wav_data.Subchunk2Size u = %u(0x%x)\n", wav_data.Subchunk2Size, wav_data.Subchunk2Size);
    printf("wav_data.Subchunk2Size d = %d(0x%x)\n", (int)wav_data.Subchunk2Size, wav_data.Subchunk2Size);

    // 计算播放时长
    double duration = (double)wav_data.Subchunk2Size / (wav_fmt.SampleRate *  wav_fmt.NumChannels * (wav_fmt.BitsPerSample / 8.0));

    printf("播放时长: %.2f 秒\n", duration);

    close(fd);
    return;
}

// 根据文件名后缀判断是否音频文件
bool IsAudioFile(const std::string &strFileName)
{
    size_t pos = strFileName.rfind('.');
    if (pos == std::string::npos) 
    {
        return false;
    }

    // 拿到后缀字符串
    std::string extension = strFileName.substr(pos);

    // 后缀转小写
    std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);

    std::vector<std::string> vtAudioList = {".mp3", ".wav", ".flac", ".ogg", ".aac", ".m4a", ".wma"};

    // 判断是否是合法的音频后缀
    for (const auto& element : vtAudioList)
    {
        if (extension == element)
        {
            return true;
        }
    }

    return false;
}

void ShowHelpInfo()
{
    printf("Usage: \n");
    printf("Play   : ./AlsaTool <wav file>\n");
    printf("Record : ./AlsaTool\n");
}



void write_wav_header(int fd, int sample_rate, int channels, int duration) 
{
    WavHeader header;
    int bits_per_sample = 16;
    int byte_rate = sample_rate * channels * (bits_per_sample / 8);
    int subchunk2_size = duration * byte_rate;
    int chunk_size = 36 + subchunk2_size;

    // 填充文件头信息
    snprintf(header.wavRiffSt.ChunkID, 5, "RIFF");
    header.wavRiffSt.ChunkSize = chunk_size;
    snprintf(header.wavRiffSt.Format, 5, "WAVE");
    snprintf(header.wavFmtSt.Subchunk1ID, 5, "fmt ");
    header.wavFmtSt.Subchunk1Size = 16;
    header.wavFmtSt.AudioFormat = 1;
    header.wavFmtSt.NumChannels = channels;
    header.wavFmtSt.SampleRate = sample_rate;
    header.wavFmtSt.ByteRate = byte_rate;
    header.wavFmtSt.BlockAlign = channels * (bits_per_sample / 8);
    header.wavFmtSt.BitsPerSample = bits_per_sample;
    snprintf(header.wavDataSt.Subchunk2ID, 5, "data");
    header.wavDataSt.Subchunk2Size = subchunk2_size;

    // 写入文件头
    write(fd, &header, sizeof(WavHeader));
}

int RecordAudio(const char *filename, int duration) 
{
    printf("Calling RecordAudio() filename = %s, duration = %d\n", filename, duration);
    unsigned int sample_rate = 48000;
    int channels = 2;
    snd_pcm_t *pcm_handle = NULL;
    snd_pcm_hw_params_t *hwParams = NULL;
    snd_pcm_uframes_t period_size = 1024;
    unsigned int bits_per_sample = 16;             	//周期数（buffer的大小）
    unsigned char *buff = NULL;
    unsigned int buf_bytes;
    int ret = -1;
    int fd = -1;

    do {
        /* 打开PCM设备 */ 
        ret = snd_pcm_open(&pcm_handle, "hw:0", SND_PCM_STREAM_CAPTURE, 0);
        if ( ret < 0) 
        {
            printf("ERROR: Can't open PCM device. %s\n", snd_strerror(ret));
            break;
        }

        // 设置硬件参数
        if (set_hw_params(pcm_handle, sample_rate, channels, bits_per_sample) < 0)
        {
            snd_pcm_close(pcm_handle);
            return 1;
        }

        // 计算缓冲区大小
        buf_bytes = period_size * channels * 2; /* 2 -> sample size */
        buff = (unsigned char *)malloc(buf_bytes);
        if(buff == NULL)
        {
            printf("buff == NULL, Error, return\n");
            break;
        }

        // 打开文件用于写入录音数据
        fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        if (fd < 0) 
        {
            perror("Unable to open file");
            break;
        }

        // 写入 WAV 文件头
        write_wav_header(fd, sample_rate, channels, duration);

        // 计算需要录制的周期数
        unsigned int total_periods = duration * sample_rate / period_size;
        for (unsigned int i = 0; i < total_periods; i++) 
        {
            ret = snd_pcm_readi(pcm_handle, buff, period_size);
            if (ret < 0) 
            {
                fprintf(stderr, "snd_pcm_readi error: %s\n", snd_strerror(ret));
                ret = snd_pcm_recover(pcm_handle, ret, 0);
                if (ret < 0) {
                    fprintf(stderr, "Failed to recover from snd_pcm_readi error: %s\n", snd_strerror(ret));
                    break;
                }
                continue;
            }

            ret = write(fd, buff, buf_bytes);
            if (ret != (int)buf_bytes)
            {
                perror("Error writing to file");
                break;
            }
        }

        printf("Recording completed successfully.\n");
        ret = 0;
    } while (0);

    // 清理资源
    if (fd != -1) {
        close(fd);
    }
    if (buff != NULL) {
        free(buff);
    }
    if (pcm_handle != NULL) {
        snd_pcm_close(pcm_handle);
    }

    return ret;
}


int PlayWavFile(const char *cstrFileName) 
{
    printf("ARM 2025 Play Wav File %s\n", cstrFileName);

    FILE *file = fopen(cstrFileName, "rb");
    if (!file) {
        perror("fopen");
        return 1;
    }

    // 读取 WAV 文件头
    unsigned char header[44];
    if (fread(header, 1, 44, file) != 44) {
        perror("fread");
        fclose(file);
        return 1;
    }

    // 解析 WAV 文件头
    unsigned int sample_rate = *(unsigned int *)&header[24];
    unsigned short channels = *(unsigned short *)&header[22];
    unsigned short bits_per_sample = *(unsigned short *)&header[34];
    printf("Parsed header: sample_rate = %d, channels = %d, bits_per_sample = %d\n", sample_rate, channels, bits_per_sample);

    snd_pcm_t *pcmHandler;
    int ret;

    // 打开 PCM 设备
    ret = snd_pcm_open(&pcmHandler, PCM_PLAYBACK_DEV, SND_PCM_STREAM_PLAYBACK, 0);
    if (ret < 0) {
        fprintf(stderr, "cannot open audio device %s (%s)\n", PCM_PLAYBACK_DEV, snd_strerror(ret));
        fclose(file);
        return 1;
    }

    // 设置硬件参数
    if (set_hw_params(pcmHandler, sample_rate, channels, bits_per_sample) < 0) {
        snd_pcm_close(pcmHandler);
        fclose(file);
        return 1;
    }

    // 获取缓冲区大小
    snd_pcm_uframes_t buffer_size;
    snd_pcm_hw_params_t *hwParams;
    snd_pcm_hw_params_malloc(&hwParams);
    snd_pcm_hw_params_current(pcmHandler, hwParams);
    snd_pcm_hw_params_get_buffer_size(hwParams, &buffer_size);
    snd_pcm_hw_params_free(hwParams);

    // 播放音频数据
    unsigned long int nTestTime = 0;
    void *buffer = malloc(buffer_size * channels * (bits_per_sample / 8));
    if (!buffer) {
        fprintf(stderr, "malloc failed\n");
        snd_pcm_close(pcmHandler);
        fclose(file);
        return 1;
    }

    int totalBytes = 0;
    
    while (1) 
    {
        nTestTime++;
        
        size_t bytes = fread(buffer, 1, buffer_size * channels * (bits_per_sample / 8), file);  // if full, bytes = buffer_size * 4
        if (bytes == 0) 
        {
            if (feof(file)) break;
            fprintf(stderr, "fread failed\n");
            break;
        }

        // // 抽帧
        // if (nTestTime % 2 != 0)
        // {
        //     continue;
        // }

        totalBytes += bytes;
        printf("Time = [%d] --- buffer_size = %ld, buffer_size * channels * (bits_per_sample / 8) = %ld\n", nTestTime, buffer_size, buffer_size * channels * (bits_per_sample / 8));
        printf("            --- bytes       = %ld,     bytes / (channels * (bits_per_sample / 8)) = %ld\n",            bytes, bytes / (channels * (bits_per_sample / 8)));
        printf("            --- channels = %ld, bits_per_sample = %ld\n", channels, bits_per_sample);

        ret = snd_pcm_writei(pcmHandler, buffer, bytes / (channels * (bits_per_sample / 8)));
        if (ret < 0) {
            fprintf(stderr, "write error: %s\n", snd_strerror(ret));
            break;
        }
    }

    // 释放资源
    free(buffer);
    snd_pcm_close(pcmHandler);
    fclose(file);

    return 0;
}

// 从 WAV 文件中选取指定时间段的数据并播放
void play_selected_audio(const char *filename, int start_time, int duration) 
{
    int fd = open(filename, O_RDONLY);
    if (fd < 0) {
        perror("Failed to open file");
        return;
    }

    WavHeader header;
    if (read(fd, &header, sizeof(WavHeader)) != sizeof(WavHeader)) {
        perror("Failed to read WAV header");
        close(fd);
        return;
    }

    // 检查是否为有效的 WAV 文件
    if (strncmp(header.wavRiffSt.ChunkID, "RIFF", 4) != 0 || strncmp(header.wavRiffSt.Format, "WAVE", 4) != 0) {
        fprintf(stderr, "Not a valid WAV file\n");
        close(fd);
        return;
    }

    /*
        每秒钟音频所含的数据(单位：字节)
        SampleRate：是音频的采样率，指的是每秒对音频信号进行采样的次数，采样率越高，音频的细节就越丰富，声音还原就越准确。
        NumChannels：代表音频的声道数。常见的有单声道（num_channels为 1）和立体声（num_channels为 2）。
                             如果是单声道，每个采样点只包含一个声道的音频信息；如果是立体声，则包含左声道和右声道两个声道的音频信息。
        BitsPerSample：是每个采样点所占用的位数，用来表示每个采样值的精度。
                                比如，常见的有 8 位、16 位、24 位等。8 位表示每个采样点可以用 256 个不同的值来表示，16 位则可以表示 65536 个不同的值，位数越高，音频的动态范围就越大，声音的质量也就越高。
    */
    long dataBytes_Per_Second = header.wavFmtSt.SampleRate * header.wavFmtSt.NumChannels * (header.wavFmtSt.BitsPerSample / 8);

    // 计算起始偏移量
    int start_offset = start_time * dataBytes_Per_Second;

    // 计算要读取的数据大小
    int data_size = duration * dataBytes_Per_Second;
    printf("data_size = %ld, duration = %ld, sample_rate = %ld, bits_per_sample= %ld\n", 
            data_size, duration, header.wavFmtSt.SampleRate, header.wavFmtSt.BitsPerSample);

    // 定位到起始位置(从头开始便宜)
    if (lseek(fd, sizeof(WavHeader) + start_offset, SEEK_SET) == -1) 
    {
        perror("Failed to seek to start position");
        close(fd);
        return;
    }

    // 初始化 ALSA 设备
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) 
    {
        perror("Failed to open PCM device");
        close(fd);
        return;
    }

    int dir;
    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_any(handle, params);
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(handle, params, header.wavFmtSt.NumChannels);
    snd_pcm_hw_params_set_rate_near(handle, params, &header.wavFmtSt.SampleRate, &dir);

    if (snd_pcm_hw_params(handle, params) < 0) 
    {
        perror("Failed to set PCM hardware parameters");
        snd_pcm_close(handle);
        close(fd);
        return;
    }

    // 分块读取并播放数据
    const int buffer_size = 4096; // 每次读取的块大小
    char *buffer = (char *)malloc(buffer_size);
    if (buffer == NULL) 
    {
        perror("Failed to allocate memory");
        snd_pcm_close(handle);
        close(fd);
        return;
    }

    int remaining = data_size;
    while (remaining > 0) 
    {
        int read_size = (remaining < buffer_size) ? remaining : buffer_size;
        if (read(fd, buffer, read_size) != read_size) 
        {
            perror("Failed to read data");
            break;
        }


        snd_pcm_sframes_t frames_written = snd_pcm_writei(handle, buffer, read_size / header.wavFmtSt.BlockAlign);
        if (frames_written < 0) 
        {
            frames_written = snd_pcm_recover(handle, frames_written, 0);
            if (frames_written < 0) 
            {
                perror("Failed to write data to PCM device");
                break;
            }
        }

        remaining -= read_size;
    }

    // 清理资源
    free(buffer);
    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    close(fd);
}


int PlayAudioFromRecvList(AudioRecvAllSt &recvAllstObj)
{
    while (recvAllstObj.bIsReceiving == false)
    {
        usleep(1000);
    }

    WavHeader header;
    memcpy(&header, &(recvAllstObj.wavHeaderObj), sizeof(WavHeader));

    // 解析 WAV 文件头
    unsigned int sample_rate = header.wavFmtSt.SampleRate;
    unsigned short channels = header.wavFmtSt.NumChannels;
    unsigned short bits_per_sample = header.wavFmtSt.BitsPerSample;
    printf("Parsed header: sample_rate = %d, channels = %d, bits_per_sample = %d\n", sample_rate, channels, bits_per_sample);

    snd_pcm_t *pcmHandler = nullptr;
    int ret;

    // 打开 PCM 设备
    ret = snd_pcm_open(&pcmHandler, PCM_PLAYBACK_DEV, SND_PCM_STREAM_PLAYBACK, 0);
    if (ret < 0) 
    {
        fprintf(stderr, "cannot open audio device %s (%s)\n", PCM_PLAYBACK_DEV, snd_strerror(ret));
        return -1;
    }

    // 设置硬件参数
    if (set_hw_params(pcmHandler, sample_rate, channels, bits_per_sample) < 0) 
    {
        snd_pcm_close(pcmHandler);
        return -1;
    }

    // 获取缓冲区大小
    snd_pcm_uframes_t buffer_size;
    snd_pcm_hw_params_t *hwParams;
    snd_pcm_hw_params_malloc(&hwParams);
    snd_pcm_hw_params_current(pcmHandler, hwParams);
    snd_pcm_hw_params_get_buffer_size(hwParams, &buffer_size);
    snd_pcm_hw_params_free(hwParams);

    printf("------------- buffer_size = %ld\n", buffer_size);

    time_t lastTime = time(NULL);
    long debugCnt = 0;
    while(1)
    {
        if (!IsQueueEmpty(&(recvAllstObj.recvList)))
        {
            AudioRecvItemSt item;
            PopQueue(&(recvAllstObj.recvList), &item);
            printf("queue have data. Cnt = %ld, this item size = %d\n", debugCnt, item.buffLen);

            ret = snd_pcm_writei(pcmHandler, item.buff, item.buffLen / (channels * (bits_per_sample / 8)));
            if (ret < 0) {
                fprintf(stderr, "write error: %s\n", snd_strerror(ret));
                ret = snd_pcm_recover(pcmHandler, ret, 0);
                if (ret < 0) {
                    fprintf(stderr, "Failed to recover from write error: %s\n", snd_strerror(ret));
                    break;
                }
            }

            lastTime = time(NULL);
            debugCnt++;
        }

        if (time(NULL) - lastTime > 2)
        {
            printf("queue is empty. exit\n");
            break;
        }
    }

    snd_pcm_close(pcmHandler);

    return 0;
}

